"""
全局异常处理中间件
统一处理各种异常并返回标准化的错误响应
"""

import traceback
from typing import Union
from fastapi import Request, HTTPException, status
from fastapi.responses import JSONResponse
from fastapi.exceptions import RequestValidationError
from sqlalchemy.exc import SQLAlchemyError, IntegrityError
from pydantic import ValidationError

from app.core.logging import get_logger

logger = get_logger(__name__)


class CustomException(Exception):
    """自定义异常基类"""
    def __init__(self, message: str, status_code: int = 500, error_code: str = None):
        self.message = message
        self.status_code = status_code
        self.error_code = error_code or "INTERNAL_ERROR"
        super().__init__(self.message)


class BusinessException(CustomException):
    """业务逻辑异常"""
    def __init__(self, message: str, error_code: str = "BUSINESS_ERROR"):
        super().__init__(message, status.HTTP_400_BAD_REQUEST, error_code)


class AuthenticationException(CustomException):
    """认证异常"""
    def __init__(self, message: str = "认证失败", error_code: str = "AUTH_ERROR"):
        super().__init__(message, status.HTTP_401_UNAUTHORIZED, error_code)


class AuthorizationException(CustomException):
    """授权异常"""
    def __init__(self, message: str = "权限不足", error_code: str = "PERMISSION_DENIED"):
        super().__init__(message, status.HTTP_403_FORBIDDEN, error_code)


class ResourceNotFoundException(CustomException):
    """资源未找到异常"""
    def __init__(self, message: str = "资源未找到", error_code: str = "RESOURCE_NOT_FOUND"):
        super().__init__(message, status.HTTP_404_NOT_FOUND, error_code)


def create_error_response(
    status_code: int,
    message: str,
    error_code: str = None,
    details: Union[str, dict] = None,
    request_id: str = None
) -> JSONResponse:
    """创建标准化错误响应"""
    error_data = {
        "success": False,
        "error": {
            "code": error_code or "UNKNOWN_ERROR",
            "message": message,
            "status_code": status_code
        }
    }
    
    if details:
        error_data["error"]["details"] = details
    
    if request_id:
        error_data["request_id"] = request_id
    
    return JSONResponse(
        status_code=status_code,
        content=error_data
    )


async def custom_exception_handler(request: Request, exc: CustomException):
    """自定义异常处理器"""
    request_id = getattr(request.state, 'request_id', None)
    
    logger.error(
        f"自定义异常: {exc.error_code}",
        error_code=exc.error_code,
        message=exc.message,
        status_code=exc.status_code,
        path=request.url.path,
        method=request.method,
        request_id=request_id
    )
    
    return create_error_response(
        status_code=exc.status_code,
        message=exc.message,
        error_code=exc.error_code,
        request_id=request_id
    )


async def http_exception_handler(request: Request, exc: HTTPException):
    """HTTP异常处理器"""
    request_id = getattr(request.state, 'request_id', None)
    
    logger.warning(
        f"HTTP异常: {exc.status_code}",
        status_code=exc.status_code,
        detail=exc.detail,
        path=request.url.path,
        method=request.method,
        request_id=request_id
    )
    
    return create_error_response(
        status_code=exc.status_code,
        message=exc.detail,
        error_code=f"HTTP_{exc.status_code}",
        request_id=request_id
    )


async def validation_exception_handler(request: Request, exc: RequestValidationError):
    """请求验证异常处理器"""
    request_id = getattr(request.state, 'request_id', None)
    
    # 格式化验证错误信息
    errors = []
    for error in exc.errors():
        field = " -> ".join(str(loc) for loc in error["loc"])
        errors.append({
            "field": field,
            "message": error["msg"],
            "type": error["type"]
        })
    
    logger.warning(
        "请求验证失败",
        errors=errors,
        path=request.url.path,
        method=request.method,
        request_id=request_id
    )
    
    return create_error_response(
        status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
        message="请求参数验证失败",
        error_code="VALIDATION_ERROR",
        details=errors,
        request_id=request_id
    )


async def sqlalchemy_exception_handler(request: Request, exc: SQLAlchemyError):
    """数据库异常处理器"""
    request_id = getattr(request.state, 'request_id', None)
    
    if isinstance(exc, IntegrityError):
        # 数据完整性错误（如唯一约束冲突）
        logger.warning(
            "数据库完整性错误",
            error=str(exc.orig),
            path=request.url.path,
            method=request.method,
            request_id=request_id
        )
        
        return create_error_response(
            status_code=status.HTTP_409_CONFLICT,
            message="数据冲突，可能存在重复记录",
            error_code="DATA_CONFLICT",
            request_id=request_id
        )
    else:
        # 其他数据库错误
        logger.error(
            "数据库操作失败",
            error=str(exc),
            path=request.url.path,
            method=request.method,
            request_id=request_id
        )
        
        return create_error_response(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            message="数据库操作失败",
            error_code="DATABASE_ERROR",
            request_id=request_id
        )


async def general_exception_handler(request: Request, exc: Exception):
    """通用异常处理器"""
    request_id = getattr(request.state, 'request_id', None)
    
    # 记录完整的错误堆栈
    error_traceback = traceback.format_exc()
    
    logger.error(
        "未处理的异常",
        error=str(exc),
        error_type=type(exc).__name__,
        traceback=error_traceback,
        path=request.url.path,
        method=request.method,
        request_id=request_id
    )
    
    # 在开发环境下返回详细错误信息
    from app.core.config import settings
    details = None
    if settings.DEBUG:
        details = {
            "error_type": type(exc).__name__,
            "traceback": error_traceback.split('\n')
        }
    
    return create_error_response(
        status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
        message="服务器内部错误",
        error_code="INTERNAL_SERVER_ERROR",
        details=details,
        request_id=request_id
    )


def setup_exception_handlers(app):
    """设置异常处理器"""
    app.add_exception_handler(CustomException, custom_exception_handler)
    app.add_exception_handler(HTTPException, http_exception_handler)
    app.add_exception_handler(RequestValidationError, validation_exception_handler)
    app.add_exception_handler(SQLAlchemyError, sqlalchemy_exception_handler)
    app.add_exception_handler(Exception, general_exception_handler)